﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static AnChao.WPF.Controls.TextBox.Controls.CommandEmun;

namespace AnChao.WPF.Controls.TextBox.Controls
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作，然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:AnChao.WPF.Controls.TextBox.Controls"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:AnChao.WPF.Controls.TextBox.Controls;assembly=AnChao.WPF.Controls.TextBox.Controls"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用，
    /// 并重新生成以避免编译错误:
    ///
    ///     在解决方案资源管理器中右击目标项目，然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:AnChaoMasterTextBox/>
    ///
    /// </summary>
    public class AnChaoMasterTextBox : System.Windows.Controls.TextBox
    {
        /// <summary>
        /// 是否正在文本框输入
        /// </summary>
        private static bool _isInnerChange = false;
        private static string latestText;

        #region MaskType 可输入的类型

        public static readonly DependencyProperty MaskTypeProperty = DependencyProperty.Register("MaskType", typeof(MaskType), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(MaskType.Any, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (d, e) =>
            {

            }));

        /// <summary>
        /// 可输入的类型
        /// </summary>
        public MaskType MaskType
        {
            get
            {
                return (MaskType)GetValue(MaskTypeProperty);
            }
            set
            {
                SetValue(MaskTypeProperty, value);
            }
        }

        #endregion

        #region EditValue 绑定的实际值

        public static readonly DependencyProperty EditValueProperty = DependencyProperty.Register("EditValue", typeof(object), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (d, e) =>
            {
                if (!_isInnerChange)
                {
                    var control = d as AnChaoMasterTextBox;
                    if (control != null)
                    {
                        if (control.EditValue == null)
                        {
                            control.Text = string.Empty;
                        }
                        else
                        {
                            control.Text = control.EditValue.ToString();
                        }

                    }
                }
            }));

        /// <summary>
        /// 绑定的实际值
        /// </summary>
        public object EditValue
        {
            get
            {
                return (object)GetValue(EditValueProperty);
            }
            set
            {
                SetValue(EditValueProperty, value);
            }
        }

        private string oldText = string.Empty;

        #endregion


        #region MaxValue 最大值

        public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double?), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// 最大值
        /// </summary>
        public double? MaxValue
        {
            get
            {
                return (double?)GetValue(MaxValueProperty);
            }
            set
            {
                SetValue(MaxValueProperty, value);
            }
        }


        #endregion


        #region MinValue 最小值

        public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(double?), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// 最小值
        /// </summary>
        public double? MinValue
        {
            get
            {
                return (double?)GetValue(MinValueProperty);
            }
            set
            {
                SetValue(MinValueProperty, value);
            }
        }

        #endregion


        #region RegexString 正则约束

        public static readonly DependencyProperty RegexStringProperty = DependencyProperty.Register("RegexString", typeof(string), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// 正则约束
        /// </summary>
        public string RegexString
        {
            get
            {
                return (string)GetValue(RegexStringProperty);
            }
            set
            {
                SetValue(RegexStringProperty, value);
            }
        }

        #endregion

        #region NumberFormat 数字格式

        public static readonly DependencyProperty NumberFormatProperty = DependencyProperty.Register("NumberFormat", typeof(string), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// 数字格式
        /// </summary>
        public string NumberFormat
        {
            get
            {
                return (string)GetValue(NumberFormatProperty);
            }
            set
            {
                SetValue(NumberFormatProperty, value);
            }
        }

        #endregion

        #region FilterChars 禁止输入的字符

        public static readonly DependencyProperty FilterCharsProperty = DependencyProperty.Register("FilterChars", typeof(string), typeof(AnChaoMasterTextBox),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// 禁止输入的字符
        /// </summary>
        public string FilterChars
        {
            get
            {
                return (string)GetValue(FilterCharsProperty);
            }
            set
            {
                SetValue(FilterCharsProperty, value);
            }
        }

        #endregion

        public AnChaoMasterTextBox()
        {
            //DefaultStyleKeyProperty.OverrideMetadata(typeof(AnChaoMasterTextBox), new FrameworkPropertyMetadata(typeof(AnChaoMasterTextBox)));
            this.Loaded += AnChaoMasterTextBox_Loaded;
        }



        private void AnChaoMasterTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            //todo
        }

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            if (_isInnerChange)
            {
                return;
            }

            try
            {
                _isInnerChange = true;

                base.OnTextChanged(e);

                if (IsDecimalType())
                {
                    if (RemoveFirstZero())
                    {
                        e.Handled = true;
                        return;
                    }
                }

                //验证输入
                if (!ValidateValue())
                {
                    int move = 0;
                    if (!string.IsNullOrEmpty(oldText) && !string.IsNullOrEmpty(this.Text))
                    {
                        move = this.Text.Length - oldText.Length;
                    }

                    int oldIndex = this.CaretIndex - move > 0 ? this.CaretIndex - move : 0;
                    this.Text = oldText;
                    if (oldIndex < Text.Length)
                    {
                        this.SelectionStart = oldIndex;
                        this.CaretIndex = oldIndex;
                    }
                    else
                    {
                        this.SelectionStart = Text.Length;
                        this.CaretIndex = Text.Length;
                    }

                    //this.SelectionStart = 0;

                    UpdateEditValue();
                    return;
                }

                ////检查小数位的精度问题
                //if (!string.IsNullOrEmpty(NumberFormat) && this.Text.Trim().Length > 0)
                //{
                //    double v = 0;
                //    Match match = Regex.Match(NumberFormat, @"^(\d+)\.(\d+)$");
                //    if (match.Groups.Count == 3 && Text.IndexOf('.') > 0 && double.TryParse(Text, out v))
                //    {
                //        int pos = Int32.Parse(match.Groups[2].Value);
                //        string text = double.Parse(this.Text).ToString(("N") + pos.ToString());

                //        //如果有小数点，去掉结尾部分的零(如果正在输入，则不要删除多余的零和小数点)
                //        if (text.IndexOf('.') > 0 && Keyboard.FocusedElement != this)
                //        {
                //            text = text.TrimEnd('0').TrimEnd('.');
                //            if (string.IsNullOrEmpty(text))
                //                text = "0";
                //        }

                //        Text = text;
                //    }
                //}


                latestText = Text;

                UpdateEditValue();
            }
            catch (Exception ex)
            {

            }
            finally
            {
                _isInnerChange = false;
            }


        }

        private void UpdateEditValue()
        {
            try
            {
                switch (MaskType)
                {
                    case MaskType.Any:
                    case MaskType.NormalString:
                    case MaskType.NumberWithComma:
                        EditValue = this.Text;
                        break;
                    case MaskType.Integer:
                        int intTemp = 0;
                        int.TryParse(this.Text, out intTemp);
                        EditValue = intTemp;
                        break;
                    case MaskType.Decimal:
                    case MaskType.SignDecimal:
                        decimal decimalTemp = 0;
                        decimal.TryParse(this.Text, out decimalTemp);
                        EditValue = decimalTemp;
                        break;
                    case MaskType.Regex:
                        break;
                    default:
                        EditValue = this.Text;
                        break;
                }
            }
            catch (Exception e)
            {
            }
        }

        #region 路由事件
        public static readonly RoutedEvent KeyInputEvent = EventManager.RegisterRoutedEvent("KeyInput", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AnChaoMasterTextBox));

        /// <summary>
        /// 当下拉框关闭后发生
        /// </summary>
        public event RoutedEventHandler KeyInput
        {
            add { AddHandler(KeyInputEvent, value); }
            remove { RemoveHandler(KeyInputEvent, value); }
        }

        private void OnKeyInputChanged()
        {
            RoutedEventArgs args = new RoutedEventArgs();
            args.RoutedEvent = KeyInputEvent;
            args.Source = this;
            RaiseEvent(args);
        }
        #endregion

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            base.OnPreviewKeyDown(e);

            if (MaskType != MaskType.Any)
            {
                //除了String类型，其他类型不允许输入空格
                if (e.Key == Key.Space)
                {
                    if (MaskType != MaskType.NormalString
                     && MaskType != MaskType.Any)
                    {
                        e.Handled = true;
                    }
                }
            }

            oldText = this.Text;
        }

        protected override void OnPreviewTextInput(TextCompositionEventArgs e)
        {
            if (_isInnerChange)
            {
                return;
            }

            base.OnPreviewTextInput(e);
            //检查是否包含非法字符
            if (!ValidateInputChars(FilterChars, e.Text))
            {
                e.Handled = true;
                return;
            }

            //进行长度控制（主要是输入中文问题）
            if ((MaxLength > 0 && Encoding.Default.GetBytes(Text).Length > MaxLength))
            {
                e.Handled = true;
                return;
            }

            OnKeyInputChanged();
        }


        /// <summary>
        /// 检查输入的字符是否在过滤字符串中
        /// </summary>
        /// <param name="filterChars"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        protected static bool ValidateInputChars(string filterChars, string input)
        {
            if (string.IsNullOrEmpty(filterChars) || string.IsNullOrEmpty(input))
                return true;

            foreach (char c in input.ToCharArray())
            {
                if (filterChars.IndexOf(c) >= 0)
                    return false;
            }

            return true;
        }

        /// <summary>
        /// 如果是数字型则去掉左侧的0
        /// </summary>
        /// <returns></returns>
        private bool RemoveFirstZero()
        {
            var result = false;
            while (IsDecimalType() && Text.Length > 1 && Text.ToString().First() == '0' && Text[1] != '.' && Text.IndexOf('.') > 0)
            {
                _isInnerChange = true;
                Text = Text.Remove(0, 1);
                CaretIndex = Text.Length;
                _isInnerChange = false;
            }
            return result;
        }

        /// <summary>
        /// 是否是数字类型
        /// </summary>
        /// <returns></returns>
        private bool IsDecimalType()
        {
            return this.MaskType == MaskType.Integer
                || this.MaskType == MaskType.Decimal
                || this.MaskType == MaskType.SignDecimal;
        }

        /// <summary>
        /// 检查输入的数据是否符合当前的MaskType类型
        /// </summary>
        /// <param name="textBox"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        protected bool ValidateValue()
        {
            bool bRet = true;
            string pattern = "";

            ///不允许首位输入逗号或点
            if (MaskType != MaskType.Any || MaskType != MaskType.NormalString)
            {
                if (Text == ",")
                {
                    return false;
                }
            }

            var text = Text.Replace(",", "");
            //输入格式控制
            switch (MaskType)
            {
                case MaskType.Integer:
                    bRet = Regex.IsMatch(text.Replace(",", ""), FormatRegex.IntegerInput);
                    break;
                case MaskType.NumberWithComma:
                    bRet = Regex.IsMatch(text, FormatRegex.NumberWithComma);
                    break;

                case MaskType.StockCode:
                    bRet = Regex.IsMatch(text, FormatRegex.StockCodeInput);
                    break;

                case MaskType.Decimal:
                    pattern = FormatRegex.DecimalInput;
                    if (!string.IsNullOrEmpty(this.NumberFormat))
                    {
                        Match match = Regex.Match(this.NumberFormat, @"^(\d+)\.(\d+)$");
                        if (match.Groups.Count == 3)
                        {
                            pattern = FormatRegex.DecimalInput_IntegerPart.Replace("$0", (Int32.Parse(match.Groups[1].Value) - Int32.Parse(match.Groups[2].Value) - 1).ToString());

                            //如果不允许小数位（类似于整数控制）
                            if (Int32.Parse(match.Groups[2].Value) == 0)
                                pattern += FormatRegex.DecimalInput_NonDecimalPart;
                            else
                                pattern += FormatRegex.DecimalInput_DecimalPart.Replace("$0", match.Groups[2].Value);

                            pattern = "^" + pattern + "$";
                        }
                    }
                    bRet = Regex.IsMatch(text, pattern);

                    break;

                case MaskType.SignDecimal:
                    pattern = FormatRegex.SignDecimalInput;
                    if (!string.IsNullOrEmpty(this.NumberFormat))
                    {
                        Match match = Regex.Match(this.NumberFormat, @"^(\d+)\.(\d+)$");
                        if (match.Groups.Count == 3)
                        {
                            pattern = FormatRegex.SignDecimalInput_IntegerPart.Replace("$0", (Int32.Parse(match.Groups[1].Value) - Int32.Parse(match.Groups[2].Value) - 1).ToString());

                            //如果不允许小数位（类似于整数控制）
                            if (Int32.Parse(match.Groups[2].Value) == 0)
                                pattern += FormatRegex.DecimalInput_NonDecimalPart;
                            else
                                pattern += FormatRegex.DecimalInput_DecimalPart.Replace("$0", match.Groups[2].Value);

                            pattern = "^" + pattern + "$";
                        }
                    }

                    if (text == "-")
                        bRet = true;
                    else
                        bRet = Regex.IsMatch(text, pattern);

                    break;


                case MaskType.Regex:
                    bRet = Regex.IsMatch(this.Text, RegexString);
                    break;

                default:
                    bRet = true;
                    break;
            }

            if (!bRet)
                return bRet;

            if (IsDecimalType())
            {
                //最大最小值控制
                double doubleValue = 0;
                if (double.TryParse(text, out doubleValue))
                {
                    if (MaxValue != null)
                    {
                        if (Math.Abs(doubleValue - (double)MaxValue) > 0.0000000001 && doubleValue > MaxValue)
                        {
                            bRet = false;
                            return bRet;
                        }
                    }

                    if (MinValue != null)
                    {
                        if (Math.Abs(doubleValue - (double)MinValue) > 0.0000000001 && doubleValue < MinValue)
                        {
                            bRet = false;
                            return bRet;
                        }
                    }
                }
            }
            //进行长度控制
            if (this.MaxLength > 0 && Encoding.Default.GetBytes(Text).Length > this.MaxLength)
            {
                bRet = false;
                return bRet;
            }

            return bRet;
        }
    }


}
